<?php
/**
 * Created by PhpStorm.
 * User: Appla
 * Date: 2017/2/8
 * Time: 14:02
 */

namespace cron\address;

require __DIR__ . '/../header.php';

use service\address\Sto1stAnd2ndCodeUtil;

class StoCodesCache
{

    /**
     * commands
     */
    const COMMAND_CLEAR = 'clear';
    const COMMAND_BUILD = 'build';
    const COMMAND_REBUILD = 'rebuild';
    const COMMAND_HELP = 'help';

    /**
     * options
     */
    const OPTION_FIRST_CODE = '1st';
    const OPTION_SECOND_CODE = '2nd';
    const OPTION_SECOND_ADDRESS_INDEXED_CODE = 'address';
    const OPTION_ALL_CODES = 'all';

    /**
     * @var array
     */
    private $optionMap = [
        self::OPTION_ALL_CODES => 7,
        self::OPTION_FIRST_CODE => 1,
        self::OPTION_SECOND_CODE => 2,
        self::OPTION_SECOND_ADDRESS_INDEXED_CODE => 4,
    ];

    /**
     * @var array
     */
    private $printTpl = [
        self::COMMAND_BUILD => 'build %s done: task is %s',
        self::COMMAND_REBUILD => 'rebuild %s done: task is %s',
        self::COMMAND_CLEAR => 'clear %s done: task is %s',
        self::COMMAND_HELP => "help:\n\t commands: [ %s ], \n\t options: [ %s ](default is ".self::OPTION_ALL_CODES.")",
    ];

    private $param;

    private $options;

    private $command;

    /**
     * @return mixed
     */
    public function run($argv = null)
    {
        if(!isset($argv[1])){
            $this->help();
            exit;
        }
        $this->command = $method = $argv[1];
        $this->options = $params = array_slice($argv, 2);
        if(isset($this->printTpl[$method]) && method_exists($this, $method)){
            return call_user_func([$this, $method], $this->parseParams($params));
        }else{
            printf('invalid method supplied,please try again');
        }
    }

    /**
     * @param null $params
     * @return int|mixed
     */
    private function parseParams($params = null)
    {
        $ret = 0;
        if(is_array($params)){
            foreach ($params as $param) {
                if(is_numeric($param) && in_array((int)$param, $this->optionMap, true)){
                    $ret += (int)$param;
                }elseif(isset($this->optionMap[$param])){
                    $ret += $this->optionMap[$param];
                }
            }
        }
        return $this->param = $ret ?: 7;
    }

    /**
     * @param int $type
     */
    public function clear($type = 7)
    {
        $this->printResult(Sto1stAnd2ndCodeUtil::cleanCache($type), __FUNCTION__);
    }

    /**
     * @param int $type
     */
    public function build($type = 7)
    {
        $this->printResult(Sto1stAnd2ndCodeUtil::buildCache($type, false), __FUNCTION__);
    }

    /**
     * @param int $type
     */
    public function rebuild($type = 7)
    {
        $this->printResult(Sto1stAnd2ndCodeUtil::buildCache($type), __FUNCTION__);
    }

    /**
     * @param array $result
     * @param string $task
     */
    private function printResult(array $result, $task = 'rebuild')
    {
        if(isset($this->printTpl[$task])){
            foreach ($result as $key => $item) {
                printf($this->printTpl[$task].PHP_EOL, $key, $item ? 'SUCCESS' : 'FAILED');
            }
        }else{
            printf('current task [%s] type is not supported '.PHP_EOL, (string)$task);
        }
    }

    /**
     * help
     */
    public function help()
    {
        printf($this->printTpl[__FUNCTION__].PHP_EOL, implode(', ', array_keys($this->printTpl)), implode(' | ', array_keys($this->optionMap)));
        $fileName = basename(__FILE__);
        $examples = [
            'build all' => [
                'php',
                $fileName,
                self::COMMAND_BUILD,
            ],
            'rebuild 1st' => [
                'php',
                $fileName,
                self::COMMAND_REBUILD,
                self::OPTION_FIRST_CODE
            ],
            'clear 1st and 2nd' => [
                'php',
                $fileName,
                self::COMMAND_CLEAR,
                self::OPTION_FIRST_CODE,
                self::OPTION_SECOND_CODE,
            ],
        ];
        echo 'example:'.PHP_EOL;
        foreach ($examples as $note => $example) {
            echo "\t".implode(' ', $example)."\t//".$note.PHP_EOL;
        }
        exit;
    }
}

(new StoCodesCache())->run($argv);